package com.study.unicom;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ailk.ecs.open.esbclient.OpenEsbClient;
import com.ailk.ecs.open.esbclient.bean.EcAopResult;
import com.ailk.ecs.open.esbclient.bean.SysParamBean;
import com.ailk.ecs.open.esbclient.sign.SignAlgorithmType;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author ：ihao ∶）
 * @date ：Created in 2021-06-10 16:35
 */
@Slf4j
public class ChinaUnicomUtil {

    private static final String SUCCESS_CODE = "00000";

    /**
     * 开发能力平台
     */
    private static String SB_SIGN_SECURITY = "75bb86e7d5c34049ada84762bf348122";
    private static String SB_APP_ID = "505698";
    private static String SB_APP_CODE = "ECS-OPEN-NEW";
    private static String SB_APP_SECRET = "DedQSNMu880nnjnYhW7BnnnA";
    private static String SB_URL = "http://open.10010.com/oppf";
    private static String DOWN_APP_ID = "MSPT0001";
    private static String GOODS_ID = "8a29ac8a762400fb017627746d8404";
    private static String SERVICE_CODE = "B1B2020V1S005";

    /**
     * 定义类对应返回的成功码
     */
    static Map<Class, String> map = new HashMap<>();

    static {
        map.put(UnifiedScoreBaseParam.SubScoreRsp.class, "660000,668888");
        map.put(UnifiedScoreBaseParam.RollbackScoreRsp.class, "661014,661009");
        map.put(UnifiedScoreBaseParam.UnifiedCoinRsp.class, "661106");
        map.put(UnifiedScoreBaseParam.OrderSelectRsp.class, "660000,661014,661015");
        map.put(UnifiedScoreBaseParam.RiskControllerResponse.class, "1");
    }

    /**
     * 发起请求
     *
     * @param object 请求参数
     * @param method 请求编码
     * @return 数据
     * @author 赖浩
     */
    private static String requestSb(JSONObject object, String method) {
        //创建应用时选择的签名加密方式
        SignAlgorithmType type = SignAlgorithmType.HmacSHA256;
        //创建应用后应用基本信息中的密钥 若签名加密方式为SHA，请使用"应用密钥"
        OpenEsbClient client = new OpenEsbClient(SB_URL, type, SB_SIGN_SECURITY);
        client.setReadTimeoutMillis(100000);
        SysParamBean sysParamBean = new SysParamBean();
        //应用ID，创建应用后可在开发者视图查阅
        sysParamBean.setAppId(SB_APP_ID);
        sysParamBean.setBusiSerial("msmds" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN) + RandomUtil.randomNumbers(5));
        //选择接入的能力编码，可位于开发者视图能力查询处查阅
        sysParamBean.setMethod(method);
        EcAopResult result = client.call(sysParamBean, object);
        return result.getResponse();
    }

    /**
     * 查询用户总积分
     *
     * @param phone 手机号
     * @return 总积分
     * @author 赖浩
     * @date 2021-05-07
     */
    public static Integer qryScoreTotalScore(String phone) {
        UnicomResponeVo responeVo = qryScore(phone);
        if (responeVo != null && responeVo.isStatus()) {
            return responeVo.getTotalScore();
        }
        return 0;
    }

    /**
     * 查询用户积分
     *
     * @param phone 用户手机号
     * @return 积分信息类
     * @author 赖浩
     * @date 2020-12-09
     */
    public static UnicomResponeVo qryScore(String phone) {
        // 请求方法
        String method = "welMall.orderQueryAvailable";
        // 请求时间
        String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        // 请求参数拼接
        UnifiedScoreBaseParam.UnifiedCoinReq unifiedCoinReq = UnifiedScoreBaseParam.UnifiedCoinReq.builder()
                .downAppId(DOWN_APP_ID).serviceNo(phone).downTime(time).dxflag("0").build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(unifiedCoinReq)), method);
        // 返回数据处理
        UnifiedScoreBaseParam.UnifiedCoinRsp unifiedCoinRsp = getDate(response, UnifiedScoreBaseParam.UnifiedCoinRsp.class, phone, null, 0);
        if (unifiedCoinRsp == null) {
            return null;
        }
        // 定向积分相加
        List<UnifiedScoreBaseParam.DxScore> dxScoreList = unifiedCoinRsp.getDxscoreList();
        Integer dxIntegral = 0;
        if (CollUtil.isNotEmpty(dxScoreList)) {
            for (UnifiedScoreBaseParam.DxScore dxScore : dxScoreList) {
                if (dxScore != null) {
                    dxIntegral += Convert.toInt(dxScore.getBalance(), 0);
                }
            }
        }
        // 返回用户积分信息
        return UnicomResponeVo.builder().txIntegral(unifiedCoinRsp.getTeleScore()).jlIntegral(unifiedCoinRsp.getAwardScore())
                .totalScore(unifiedCoinRsp.getTotalScore()).phone(phone).type("8").dxIntegral(dxIntegral).status(true).build();
    }

    /**
     * 扣减积分
     *
     * @param phone        用户手机号
     * @param coin         扣减的金币
     * @param orderNo      买什么都省订单号
     * @param goodsMessage 自定义展示标题
     * @return 扣减积分返回类
     * @author 赖浩
     * @date 2020-12-09
     */
    public static UnicomResponeVo subScore(String phone, int coin, String orderNo, String goodsMessage) {
        // 请求方法
        String method = "welMall.markOrder";
        // 请求时间
        String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        // 请求参数拼接
        UnifiedScoreBaseParam.SubScoreReq subScoreReq = UnifiedScoreBaseParam.SubScoreReq.builder().downAppId(DOWN_APP_ID).downTime(time).placeOrderSerialNum(orderNo)
                .serviceNo(phone).serviceCode(SERVICE_CODE).goodsIds(GOODS_ID).goodsNum(Convert.toStr(coin))
                .channelCode("MSMDS").channelName("积分福利商城").goodsMessage(goodsMessage).build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(subScoreReq)), method);
        // 处理返回数据
        UnifiedScoreBaseParam.SubScoreRsp date = getDate(response, UnifiedScoreBaseParam.SubScoreRsp.class, phone, orderNo, coin);
        if (date != null) {
            if (date.isStatus()) {
                // 成功
                return UnicomResponeVo.builder().status(true)
                        .txIntegral(Convert.toInt(date.getTeleScore())).jlIntegral(Convert.toInt(date.getAwardScore()))
                        .awarwdOrderNo(date.getAwardOrderNo()).dxIntegral(Convert.toInt(date.getAwardScoreDx()))
                        .dxOrderNo(date.getDxOrderNo()).pSerialNo(date.getPSerialNo()).tranIdo(date.getTranIdo())
                        .transNo(date.getPOrderNo()).unifiedType(1).orderNo(orderNo).build();
            }
            // 失败有信息
            return UnicomResponeVo.builder().status(false).msg(date.getMessage()).build();
        }
        // 失败无信息
        return UnicomResponeVo.builder().status(false).build();
    }

    /**
     * 回退积分
     *
     * @param phone   用户手机号
     * @param orderNo 扣减返回的流水号 pOrderNo
     * @return 回退积分详情
     * @author 赖浩
     * @date 2020-12-09
     */
    public static UnicomResponeVo rollbackScore(String phone, String orderNo) {
        // 请求方法
        String method = "welMall.orderBack";
        // 请求时间
        String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        // 请求参数拼接
        UnifiedScoreBaseParam.RollbackScoreReq rollbackScoreReq = UnifiedScoreBaseParam.RollbackScoreReq.builder()
                .downAppId(DOWN_APP_ID).downTime(time).serviceNo(phone).placeOrderSerialNum(orderNo)
                .serviceCode(SERVICE_CODE).build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(rollbackScoreReq)), method);
        // 响应数据处理
        UnifiedScoreBaseParam.RollbackScoreRsp date = getDate(response, UnifiedScoreBaseParam.RollbackScoreRsp.class, phone, null, 0);
        // 转旧格式vo
        UnicomResponeVo responeVo = UnicomResponeVo.builder().build();
        if (date != null) {
            responeVo.setStatus(date.isStatus());
        }
        return responeVo;
    }

    /**
     * 订单查询
     *
     * @param phone    用户手机号
     * @param orderNo  扣减返回的流水号 数据库字段-orderNo
     * @param operType 01 查询扣分，02 查询回退
     * @return 订单详情
     * @author 赖浩
     * @date 2020-12-09
     */
    public static UnicomResponeVo orderSelect(String phone, String orderNo, String operType) {
        // 请求方法
        String method = "welMall.orderSelectDedu";
        // 请求时间
        String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        // 请求参数拼接
        UnifiedScoreBaseParam.OrderSelectReq orderSelectReq = UnifiedScoreBaseParam.OrderSelectReq.builder().downAppId(DOWN_APP_ID).downTime(time).serviceNo(phone)
                .serialNum(orderNo).operType(operType).serviceCode(SERVICE_CODE).build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(orderSelectReq)), method);
        // 响应数据处理
        UnifiedScoreBaseParam.OrderSelectRsp date = getDate(response, UnifiedScoreBaseParam.OrderSelectRsp.class, phone, null, 0);
        if (date != null) {
            return UnicomResponeVo.builder().status(date.isStatus()).orderNo(orderNo).transNo(date.getPOrderNo()).jlIntegral(date.getAwardScore())
                    .txIntegral(date.getTeleScore()).dxIntegral(date.getAwardScore_dx()).build();
        }
        return UnicomResponeVo.builder().status(false).build();
    }

    /**
     * 订单查询
     *
     * @param time 时间日期格式
     * @return 当天积分账单
     * @author 赖浩
     * @date 2020-12-09
     */
    public static UnifiedScoreBaseParam.OrderBillRsp getOrderBill(String time) {
        // 请求方法
        String method = "welMall.OrderRecon";
        // 请求参数拼接
        UnifiedScoreBaseParam.OrderBillReq orderBillReq = UnifiedScoreBaseParam.OrderBillReq.builder().appId(DOWN_APP_ID)
                .sufCreateTime(time).build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(orderBillReq)), method);
        // 响应数据处理
        return getDate(response, UnifiedScoreBaseParam.OrderBillRsp.class, null, null, 0);
    }

    /**
     * 获取返回的数据
     *
     * @param response 响应数据
     * @param clazz    定义类型
     * @param phone    手机号
     * @param orderNo  订单号
     * @param coin     扣减的积分
     * @return 返回转换后实体
     * @author 赖浩
     * @date 2020-12-08
     */
    private static <T> T getDate(String response, Class<T> clazz, String phone, String orderNo, int coin) {
        if (StrUtil.isEmpty(response) || !JSONUtil.isJson(response)) {
            log.error("返回数据为空：{}", response);
            return null;
        }
        // 转基础响应类
        UnifiedScoreBaseParam.BaseResponse baseResponse = JSONObject.parseObject(response, UnifiedScoreBaseParam.BaseResponse.class);
        if (baseResponse != null) {
            if (SUCCESS_CODE.equals(baseResponse.getRespCode())) {
                // 响应结果类
                UnifiedScoreBaseParam.BaseResult result = baseResponse.getResult();
                String successCode = map.get(clazz);
                if (result == null) {
                    log.error("返回数据异常：{}", baseResponse.getRespDesc());
                    return null;
                }
                // 普通判断
                if (StrUtil.isNotEmpty(successCode) && successCode.equals(result.getCode())) {
                    return JSONObject.parseObject(result.getContent(), clazz);
                }
                // 多code状态判断
                if (successCode.contains(",")) {
                    // 根据响应类型拿返回coode 进行切割判断
                    for (String code : successCode.split(",")) {
                        if (StrUtil.isNotEmpty(code) && code.equals(result.getCode())) {
                            JSONObject parseObject = JSONObject.parseObject(result.getContent());
                            if (CollUtil.isNotEmpty(parseObject) || (StrUtil.isNotEmpty(result.getMessage()) && result.getMessage().contains("已成功"))) {
                                // 成功
                                if (parseObject == null) {
                                    parseObject = new JSONObject();
                                }
                                parseObject.put("msg", result.getMessage());
                                parseObject.put("status", true);
                                return parseObject.toJavaObject(clazz);
                            }
                            // 失败 增加错误信息
                            return BeanUtil.toBean(result, clazz);
                        }

                    }
                }
            }
            if ("999997".equals(baseResponse.getRespCode()) && coin > 0) {
                // 异常code
                log.error("异常--->{}", baseResponse.getRespDesc());
            }
        }
        return null;
    }

    /**
     * 风控返回编码	风控返回描述
     * 1 建议通过
     * 2 建议使用简单验证措施
     * 3 建议使用中等验证措施
     * 4 建议使用复杂验证措施
     * 5 建议拒绝
     * -1  风控返回异常
     * 0   宽带用户
     * 返现控制校检
     *
     * @param phone 请求手机号
     * @param ip    请求ip
     * @return 风控返回编码
     * @author 赖浩
     * @date 2021-03-23
     */
    public static int riskCheck(String phone, String ip) {
        // 请求方法
        String method = "RISKCONTROL.RISKCONTROL_DECISION";
        // 请求参数拼接
        UnifiedScoreBaseParam.RiskControllerRequest controllerRequest = UnifiedScoreBaseParam.RiskControllerRequest.builder()
                .userId(phone)
                .userIp(ip)
                .sceneCode("00")
                .riskControlCode("PloyEventIdQD003")
                .agencyId("superfriday")
                .build();
        UnifiedScoreBaseParam.UNI_BSS_BODY req = UnifiedScoreBaseParam.UNI_BSS_BODY.builder().request(controllerRequest).build();
        // 请求联通
        String response = requestSb(JSONObject.parseObject(JSONObject.toJSONString(req)), method);
        if (!JSONUtil.isJson(response)) {
            return -1;
        }
        UnifiedScoreBaseParam.BaseResponse baseResponse = JSONObject.parseObject(response, UnifiedScoreBaseParam.BaseResponse.class);
        if (checkRiskResult(baseResponse)) {
            UnifiedScoreBaseParam.RiskControllerResponse riskControllerResponse = baseResponse.getResult().getUniBssBody().getRiskControllerResponse();
            return Convert.toInt(riskControllerResponse.getRespInfo().getReturnCode(), -1);
        }

        //当风控接口出错时，不进行校验
        return -1;
    }

    /**
     * 校验风控接口响应结果是否成功
     *
     * @param baseResponse 风控接口响应结果
     * @return 结果
     * @author 胡玉喜
     * @date 2021/4/2 17:39
     */
    private static boolean checkRiskResult(UnifiedScoreBaseParam.BaseResponse baseResponse) {
        return baseResponse != null && SUCCESS_CODE.equals(baseResponse.getRespCode()) && baseResponse.getResult() != null
                && baseResponse.getResult().getUniBssBody() != null;
    }

    public static void main(String[] args) throws Exception {
        String string = FileUtil.readUtf8String("C:\\Users\\laihao\\Desktop\\unicom_phone.txt");
        List<String> phones = StrUtil.split(string, '\n');
//        StringBuilder stringBuilder = new StringBuilder();
//        for (String phone : phones) {
//            try {
//                phone = phone.replaceAll("\r", "");
//                stringBuilder.append(phone).append(" -> ").append(qryScoreTotalScore(phone)).append("\n");
//            } catch (Exception e) {
//                log.error(e.getMessage());
//            }
//        }
//        FileUtil.writeUtf8String(stringBuilder.toString(), "C:\\Users\\laihao\\Desktop\\phoneIntegralInfo.txt");
        select(phones);
    }

    public static void select(List<String> list) throws Exception {
        // 开始时间
        long start = System.currentTimeMillis();
        // 数据切割 500一条线程
        List<List<String>> split = CollUtil.split(list, 500);
        // 创建线程
        ExecutorService exec = Executors.newFixedThreadPool(split.size());
        // 定义一个任务集合
        List<Callable<String>> tasks = new ArrayList<>();
        Callable<String> task;
        // 确定每条线程的数据
        for (List<String> strings : split) {
            final List<String> listStr = strings;
            task = () -> {
                StringBuilder stringBuilder = new StringBuilder();
                for (String phone : listStr) {
                    if (phone != null) {
                        try {
                            phone = phone.replaceAll("\r", "");
                            stringBuilder.append(phone).append(" -> ").append(qryScoreTotalScore(phone)).append("\n");
                        } catch (Exception e) {
                            log.error(e.getMessage());
                        }
                    }
                }
                return stringBuilder.toString();
            };
            // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
            tasks.add(task);
        }
        List<Future<String>> results = exec.invokeAll(tasks);
        for (Future<String> future : results) {
            String s = future.get();
            FileUtil.appendUtf8String(s, "C:\\Users\\laihao\\Desktop\\phoneIntegralInfo.txt");
        }
        // 关闭线程池
        exec.shutdown();
        System.out.println("线程任务执行结束");
        System.err.println("执行任务消耗了 ：" + (System.currentTimeMillis() - start) + "毫秒");
    }

}
